package br.com.pmz.utilidades.util;

import java.util.Collection;

import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Restrictions;

/**
 * Classe com fun&ccedil;&otilde;es utilit&aacute;rias para adicioar objetos
 * dentro de uma collection.
 *
 * @author Pedro Manoel Zanin
 */
public final class UtilCollection {

    /**
     * Construtor privado para classes utilit&aacute;rias.
     */
    private UtilCollection() {
    }

    /**
     * Adiciona elementos na collection.
     *
     * @param colle
     *            Collection que conter&aacute; os objetos.
     * @param crit
     *            Criterio que ser&aacute; adicionado.
     * @param label
     *            Nome da propriedade no objeto java.
     */
    private static void add(final Collection < Criterion > colle,
            final Criterion crit, final String label) {
        if (Util.notEmpty(label)) {
            colle.add(crit);
        }
    }

    /**
     * Adiciona elementos na collection.
     *
     * @param colle
     *            Collection que conter&aacute; os objetos.
     * @param crit
     *            Criterio que ser&aacute; adicionado.
     * @param label
     *            Nome da propriedade no objeto java.
     * @param value
     *            Valor da propriedade no objeto java.
     */
    private static void add(final Collection < Criterion > colle,
            final Criterion crit, final String label, final Object value) {
        if (Util.notEmpty(label) && Util.notEmpty(value)) {
            add(colle, crit, label);
        }
    }

    /**
     * Adiciona elementos na collection.
     *
     * @param colle
     *            Collection que conter&aacute; os objetos.
     * @param crit
     *            Criterio que ser&aacute; adicionado.
     * @param label
     *            Nome da propriedade no objeto java.
     * @param low
     *            Menor valor da propriedade no objeto java.
     * @param high
     *            Maior valor da propriedade no objeto java.
     */
    private static void add(final Collection < Criterion > colle,
            final Criterion crit, final String label, final Object low,
            final Object high) {
        if (Util.notEmpty(high)) {
            add(colle, crit, label, low);
        }
    }

    /**
     * Adiciona elementos na collection.
     *
     * @param colle
     *            Collection que conter&aacute; os objetos.
     * @param crit
     *            Criterio que ser&aacute; adicionado.
     * @param labelF
     *            Nome da propriedade no objeto java da primeira
     *            compara&ccedil;&atilde;o.
     * @param valueF
     *            Valor da propriedade do objeto java da primeira
     *            compara&ccedil;&atilde;o.
     * @param labelL
     *            Nome da propriedade no objeto java da &uacute;ltima
     *            compara&ccedil;&atilde;o.
     * @param valueL
     *            Valor da propriedade do objeto java da &uacute;ltima
     *            compara&ccedil;&atilde;o.
     */
    private static void add(final Collection < Criterion > colle,
            final Criterion crit, final String labelF, final Object valueF,
            final String labelL, final Object valueL) {
        if (Util.notEmpty(labelL)) {
            add(colle, crit, labelF, valueF, valueL);
        }
    }

    /**
     * Adiciona uma compara&ccedil;&atilde;o de igualdade na clausula where da
     * query.
     *
     * @param colle
     *            Collection que conter&aacute; os objetos.
     * @param label
     *            Nome da propriedade do objeto.
     * @param value
     *            Valor que ser&aacute; passado na query.
     */
    public static void addEq(final Collection < Criterion > colle,
            final String label, final Object value) {
        add(colle, Restrictions.eq(label, value), label, value);
    }

    /**
     * Adiciona uma compara&ccedil;&atilde;o de n&atilde;o igualdade na clausula
     * where da query.
     *
     * @param colle
     *            Collection que conter&aacute; os objetos.
     * @param label
     *            Nome do parametro que ir&aacute; fazer a busca no banco.
     * @param value
     *            Valor que ser&aacute; passado na query.
     */
    public static void addNe(final Collection < Criterion > colle,
            final String label, final Object value) {
        add(colle, Restrictions.ne(label, value), label, value);
    }

    /**
     * Adiciona uma compara&ccedil;&atilde;o de igualdade de texto na clausula
     * where da query. E colocando todos os caracteres como lower.
     *
     * @param colle
     *            Collection que conter&aacute; os objetos.
     * @param label
     *            Nome do parametro que ir&aacute; fazer a busca no banco.
     * @param value
     *            Valor que ser&aacute; passado na query.
     */
    public static void addIlike(final Collection < Criterion > colle,
            final String label, final String value) {
        add(colle, Restrictions.ilike(label, value, MatchMode.ANYWHERE), label,
                value);
    }

    /**
     * Adiciona uma compara&ccedil;&atilde;o onde o valor do banco ter&aacute;
     * que ser entre os dois parametros passados na clausula where da query.
     *
     * @param colle
     *            Collection que conter&aacute; os objetos.
     * @param label
     *            Nome do parametro que ir&aacute; fazer a busca no banco.
     * @param low
     *            Menor valor que ser&aacute; passado para a
     *            compara&ccedil;&atilde;o.
     * @param high
     *            Maior valor que ser&aacute; passado para a
     *            compara&ccedil;&atilde;o.
     */
    public static void addBetween(final Collection < Criterion > colle,
            final String label, final Object low, final Object high) {
        add(colle, Restrictions.between(label, low, high), label, low, high);
    }

    /**
     * Adiciona uma compara&ccedil;&atilde;o entre uma lista de valores passados
     * na clausula where da query.
     *
     * @param colle
     *            Collection que conter&aacute; os objetos.
     * @param label
     *            Nome do parametro que ir&aacute; fazer a busca no banco.
     * @param values
     *            Valor que ser&aacute; passado na query.
     */
    public static void addIn(final Collection < Criterion > colle,
            final String label, final Collection < Object > values) {
        add(colle, Restrictions.in(label, values), label, values);
    }

    /**
     * Adiciona uma compara&ccedil;&atilde;o onde o valor deve ser vazio.
     *
     * @param colle
     *            Collection que conter&aacute; os objetos.
     * @param label
     *            Nome do parametro que ir&aacute; fazer a busca no banco.
     */
    public static void addIsEmpty(final Collection < Criterion > colle,
            final String label) {
        add(colle, Restrictions.isEmpty(label), label);
    }

    /**
     * Adiciona uma compara&ccedil;&atilde;o onde o valor n&atilde;o pode ser
     * vazio.
     *
     * @param colle
     *            Collection que conter&aacute; os objetos.
     * @param label
     *            Nome do parametro que ir&aacute; fazer a busca no banco.
     */
    public static void addIsNotEmpty(final Collection < Criterion > colle,
            final String label) {
        add(colle, Restrictions.isNotEmpty(label), label);
    }

    /**
     * Adiciona uma compara&ccedil;&atilde;o onde o valor n&atilde;o pode ser
     * null.
     *
     * @param colle
     *            Collection que conter&aacute; os objetos.
     * @param label
     *            Nome do parametro que ir&aacute; fazer a busca no banco.
     */
    public static void addIsNotNull(final Collection < Criterion > colle,
            final String label) {
        add(colle, Restrictions.isNotNull(label), label);
    }

    /**
     * Adiciona uma compara&ccedil;&atilde;o onde o valor deve ser null.
     *
     * @param colle
     *            Collection que conter&aacute; os objetos.
     * @param label
     *            Nome do parametro que ir&aacute; fazer a busca no banco.
     */
    public static void addIsNull(final Collection < Criterion > colle,
            final String label) {
        add(colle, Restrictions.isNull(label), label);
    }

    /**
     * Adiciona uma compara&ccedil;&atilde;o onde o valor deve ser menor ou
     * igual.
     *
     * @param colle
     *            Collection que conter&aacute; os objetos.
     * @param label
     *            Nome do parametro que ir&aacute; fazer a busca no banco.
     * @param value
     *            Valor que ser&aacute; passado na query.
     */
    public static void addLe(final Collection < Criterion > colle,
            final String label, final Object value) {
        add(colle, Restrictions.le(label, value), label, value);
    }

    /**
     * Adiciona uma compara&ccedil;&atilde;o onde o valor deve ser menor.
     *
     * @param colle
     *            Collection que conter&aacute; os objetos.
     * @param label
     *            Nome do parametro que ir&aacute; fazer a busca no banco.
     * @param value
     *            Valor que ser&aacute; passado na query.
     */
    public static void addLt(final Collection < Criterion > colle,
            final String label, final Object value) {
        add(colle, Restrictions.lt(label, value), label, value);
    }

    /**
     * Adiciona uma compara&ccedil;&atilde;o onde o valor deve ser maior ou
     * igual.
     *
     * @param colle
     *            Collection que conter&aacute; os objetos.
     * @param label
     *            Nome do parametro que ir&aacute; fazer a busca no banco.
     * @param value
     *            Valor que ser&aacute; passado na query.
     */
    public static void addGe(final Collection < Criterion > colle,
            final String label, final Object value) {
        add(colle, Restrictions.ge(label, value), label, value);
    }

    /**
     * Adiciona uma compara&ccedil;&atilde;o onde o valor deve ser maior.
     *
     * @param colle
     *            Collection que conter&aacute; os objetos.
     * @param label
     *            Nome do parametro que ir&aacute; fazer a busca no banco.
     * @param value
     *            Valor que ser&aacute; passado na query.
     */
    public static void addGt(final Collection < Criterion > colle,
            final String label, final Object value) {
        add(colle, Restrictions.gt(label, value), label, value);
    }

    /**
     * Adiciona uma compara&ccedil;&atilde;o utiizando OR ao inv&eacute;s de
     * AND. Os dois par&acirc;metros de compara&ccedil;&atilde;o ser&atilde;o
     * utilizando igual.
     *
     * @param colle
     *            Collection que conter&aacute; os objetos.
     * @param labelF
     *            Nome da propriedade no objeto java da primeira
     *            compara&ccedil;&atilde;o.
     * @param valueF
     *            Valor da propriedade do objeto java da primeira
     *            compara&ccedil;&atilde;o.
     * @param labelL
     *            Nome da propriedade no objeto java da &uacute;ltima
     *            compara&ccedil;&atilde;o.
     * @param valueL
     *            Valor da propriedade do objeto java da &uacute;ltima
     *            compara&ccedil;&atilde;o.
     */
    public static void addEqEqOr(final Collection < Criterion > colle,
            final String labelF, final Object valueF, final String labelL,
            final Object valueL) {
        add(colle, Restrictions.or(Restrictions.eq(labelF, valueF),
                Restrictions.eq(labelL, valueL)), labelF, valueF, labelL,
                valueL);
    }

    /**
     * Adiciona uma compara&ccedil;&atilde;o utiizando OR ao inv&eacute;s de
     * AND. O primeiro par&acirc;metros de compara&ccedil;&atilde;o ser&aacute;
     * igual e o segundo ser&aacute; utilizando diferente(not equals).
     *
     * @param colle
     *            Collection que conter&aacute; os objetos.
     * @param labelF
     *            Nome da propriedade no objeto java da primeira
     *            compara&ccedil;&atilde;o.
     * @param valueF
     *            Valor da propriedade do objeto java da primeira
     *            compara&ccedil;&atilde;o.
     * @param labelL
     *            Nome da propriedade no objeto java da &uacute;ltima
     *            compara&ccedil;&atilde;o.
     * @param valueL
     *            Valor da propriedade do objeto java da &uacute;ltima
     *            compara&ccedil;&atilde;o.
     */
    public static void addEqNeOr(final Collection < Criterion > colle,
            final String labelF, final Object valueF, final String labelL,
            final Object valueL) {
        add(colle, Restrictions.or(Restrictions.eq(labelF, valueF),
                Restrictions.ne(labelL, valueL)), labelF, valueF, labelL,
                valueL);
    }

    /**
     * Adiciona uma compara&ccedil;&atilde;o utiizando OR ao inv&eacute;s de
     * AND. O primeiro par&acirc;metros de compara&ccedil;&atilde;o ser&aacute;
     * utilizando diferente(not equals) e o segundo ir&aacute; utilizar o igual.
     *
     * @param colle
     *            Collection que conter&aacute; os objetos.
     * @param labelF
     *            Nome da propriedade no objeto java da primeira
     *            compara&ccedil;&atilde;o.
     * @param valueF
     *            Valor da propriedade do objeto java da primeira
     *            compara&ccedil;&atilde;o.
     * @param labelL
     *            Nome da propriedade no objeto java da &uacute;ltima
     *            compara&ccedil;&atilde;o.
     * @param valueL
     *            Valor da propriedade do objeto java da &uacute;ltima
     *            compara&ccedil;&atilde;o.
     */
    public static void addNeEqOr(final Collection < Criterion > colle,
            final String labelF, final Object valueF, final String labelL,
            final Object valueL) {
        add(colle, Restrictions.or(Restrictions.ne(labelF, valueF),
                Restrictions.eq(labelL, valueL)), labelF, valueF, labelL,
                valueL);
    }

    /**
     * Adiciona uma compara&ccedil;&atilde;o utiizando OR ao inv&eacute;s de
     * AND. Os dois par&acirc;metros de compara&ccedil;&atilde;o ser&atilde;o
     * utilizando diferente (not equals).
     *
     * @param colle
     *            Collection que conter&aacute; os objetos.
     * @param labelF
     *            Nome da propriedade no objeto java da primeira
     *            compara&ccedil;&atilde;o.
     * @param valueF
     *            Valor da propriedade do objeto java da primeira
     *            compara&ccedil;&atilde;o.
     * @param labelL
     *            Nome da propriedade no objeto java da &uacute;ltima
     *            compara&ccedil;&atilde;o.
     * @param valueL
     *            Valor da propriedade do objeto java da &uacute;ltima
     *            compara&ccedil;&atilde;o.
     */
    public static void addNeNeOr(final Collection < Criterion > colle,
            final String labelF, final Object valueF, final String labelL,
            final Object valueL) {
        add(colle, Restrictions.or(Restrictions.ne(labelF, valueF),
                Restrictions.ne(labelL, valueL)), labelF, valueF, labelL,
                valueL);
    }
}
